use std::path::PathBuf;

use log::LevelFilter;

// 自定义类型
pub enum Duplicate {
    /// No messages are duplicated.
    None = 0,
    /// Only error messages are duplicated.
    Error = 1,
    /// Error and warn messages are duplicated.
    Warn = 2,
    /// Error, warn, and info messages are duplicated.
    Info = 3,
    /// Error, warn, info, and debug messages are duplicated.
    Debug = 4,
    /// All messages are duplicated.
    Trace = 5,
    /// All messages are duplicated.
    All = 6,
}

impl From<Duplicate> for flexi_logger::Duplicate {
    fn from(val: Duplicate) -> Self {
        match val {
            Duplicate::None => flexi_logger::Duplicate::None,
            Duplicate::Error => flexi_logger::Duplicate::Error,
            Duplicate::Warn => flexi_logger::Duplicate::Warn,
            Duplicate::Info => flexi_logger::Duplicate::Info,
            Duplicate::Debug => flexi_logger::Duplicate::Debug,
            Duplicate::Trace => flexi_logger::Duplicate::Trace,
            Duplicate::All => flexi_logger::Duplicate::All,
        }
    }
}

impl From<u8> for Duplicate {
    fn from(val: u8) -> Self {
        match val {
            0 => Duplicate::None,
            1 => Duplicate::Error,
            2 => Duplicate::Warn,
            3 => Duplicate::Info,
            4 => Duplicate::Debug,
            5 => Duplicate::Trace,
            6 => Duplicate::All,
            _ => unreachable!(),
        }
    }
}

pub struct LoggerConfig {
    pub level: LevelFilter,
    pub directory: PathBuf,
    pub basename: String,
    pub suffix: String,
    pub rotate_size: u64,
    pub duplicate_to_stdout: Duplicate,
}

impl Default for LoggerConfig {
    fn default() -> Self {
        Self {
            level: LevelFilter::Info,
            directory: PathBuf::from("logs"),
            basename: "app".to_string(),
            suffix: "log".to_string(),
            rotate_size: 100 * 1024 * 1024,
            duplicate_to_stdout: Duplicate::None,
        }
    }
}

impl LoggerConfig {
    pub fn builder() -> LoggerConfigBuilder {
        LoggerConfigBuilder::default()
    }
}

#[derive(Default)]
pub struct LoggerConfigBuilder {
    level: Option<LevelFilter>,
    directory: Option<PathBuf>,
    basename: Option<String>,
    suffix: Option<String>,
    rotate_size: Option<u64>,
    duplicate_to_stdout: Option<Duplicate>,
}

impl LoggerConfigBuilder {
    pub fn level(mut self, level: LevelFilter) -> Self {
        self.level = Some(level);
        self
    }
    pub fn directory<P: Into<PathBuf>>(mut self, directory: P) -> Self {
        self.directory = Some(directory.into());
        self
    }
    pub fn basename<S: Into<String>>(mut self, basename: S) -> Self {
        self.basename = Some(basename.into());
        self
    }
    pub fn suffix<S: Into<String>>(mut self, suffix: S) -> Self {
        self.suffix = Some(suffix.into());
        self
    }
    pub fn rotate_size(mut self, rotate_size: u64) -> Self {
        self.rotate_size = Some(rotate_size);
        self
    }
    pub fn duplicate_to_stdout(mut self, duplicate: Duplicate) -> Self {
        self.duplicate_to_stdout = Some(duplicate);
        self
    }
    pub fn build(self) -> LoggerConfig {
        LoggerConfig {
            level: self.level.unwrap_or(LevelFilter::Info),
            directory: self.directory.unwrap_or_else(|| PathBuf::from("logs")),
            basename: self.basename.unwrap_or_else(|| "app".to_string()),
            suffix: self.suffix.unwrap_or_else(|| "log".to_string()),
            rotate_size: self.rotate_size.unwrap_or(100 * 1024 * 1024),
            duplicate_to_stdout: self.duplicate_to_stdout.unwrap_or(Duplicate::All),
        }
    }
}
